package com.lry;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Semaphore;

/**
 * 接受者
 */
@Slf4j
public class Acceptor {

    //之前的提案编号
    private volatile Integer lastRound;

    public Integer value;

    private Integer valueRound;

    private String name;

    public boolean error;

    private Semaphore semaphore = new Semaphore(1);

    public Acceptor(String name){
        this.name = name;
    }


    public Phase1Resp prepareRequest(Integer round) {

        if(error){
            log.info("{},prepareRequest节点挂了，lastRound={},round={}",name,lastRound,round);
            //模拟节点挂掉 无响应
            return null;
        }
        try {
            semaphore.acquire();
            //如果之前的提案编号为空，或者当前编号>=之前的编号
            if(null==lastRound || round>=lastRound){
                log.info("{},prepareRequest,接受请求，lastRound={},round={}",name,lastRound,round);
//                将自身的last_round = 请求中的round
//                返回应答,带上自身的last_round, 上一个接受的value和value_round
                lastRound = round;
                return Phase1Resp.builder().
                        respCode(RespEnums.SUCCESS.getResp()).
                        lastRound(lastRound).
                        value(value).
                        valueRound(valueRound).build();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            semaphore.release();
        }
        //如果收到的值比原先值小，丢弃返回拒绝，否则更新
        log.info("{},prepareRequest，丢弃请求，lastRound={},round={}",name,lastRound,round);
        return Phase1Resp.builder().respCode(RespEnums.REJECTED.getResp()).build();
    }

//    如果 round != last_round 说明存在冲突直接拒绝请求
//    value 写入本地，应用于状态机
//    将成功或失败的结果返回给proposer
    public Integer acceptRequest(Integer round, Integer value) {
        if(null==lastRound||round<lastRound){
            log.info("{},acceptRequest，丢弃请求，lastRound={},round={}，value={}",name,lastRound,round,value);
            return RespEnums.REJECTED.getResp();
        }
        this.valueRound = round;
        this.value = value;
        log.info("{},acceptRequest,接受请求，lastRound={},round={}，value={}",name,lastRound,round,value);

        return RespEnums.SUCCESS.getResp();
    }

    @Override
    public String toString() {
        return name;
    }
}

